//! 一些简单的 parser
use crate::parser::*;

/// 返回一个匹配特定前缀的 parse
pub fn match_literal<'a>(expected: &'a str) -> impl Parser<'a, ()> {
    move |input: &'a str| {
        if input.starts_with(expected) {
            Ok((&input[expected.len()..], ()))
        } else {
            Err(input)
        }
    }
}

/// 匹配一个标识符，语法是 字母开头，后面跟任意个 字母、数字或者 "-"
pub fn identifier(input: &str) -> ParserResult<&str> {
    let mut result_len = 0;
    let mut chars = input.chars();

    match chars.next() {
        Some(c) if c.is_alphabetic() => result_len += c.len_utf8(),
        _ => return Err(input),
    }

    for c in chars {
        if c.is_alphanumeric() || c == '-' {
            result_len += c.len_utf8();
        } else {
            break;
        }
    }

    if result_len == 0 {
        Err(input)
    } else {
        Ok((&input[result_len..], &input[..result_len]))
    }
}

/// 匹配任何字符
pub fn any_char(input: &str) -> ParserResult<char> {
    if let Some(c) = input.chars().next() {
        Ok((&input[c.len_utf8()..], c))
    } else {
        Err(input)
    }
}

/// 匹配单个 空白字符
pub fn whitespace_char(input: &str) -> ParserResult<()> {
    map(pred(any_char, |c| c.is_whitespace()), |_| ()).parse(input)
}

/// 匹配一个或多个空白字符
pub fn space<'a>(input: &'a str) -> ParserResult<'a, Vec<()>> {
    one_or_more(whitespace_char).parse(input)
}

/// 匹配 0 个或多个空白字符
pub fn space0<'a>(input: &'a str) -> ParserResult<'a, Vec<()>> {
    zero_or_more(whitespace_char).parse(input)
}

pub fn whitespace_wrap<'a, T, P>(parser: P) -> impl Parser<'a, T>
where
    P: Parser<'a, T> + 'a,
{
    right(space0, left(parser, space0))
}
